import { Injectable } from '@angular/core';
import { RestService } from '@abp/ng.core';
import { Observable } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';

export interface RedisStatusDto {
  isEnabled: boolean;
  configuration: string;
  instanceName: string;
  status: string;
  message: string;
  usedMemory: string;
  maxMemory: string;
  connectedClients: string;
  totalCommands: string;
  cacheHitRate: string;
  totalKeys: number;
  bookStoreKeys: number;
  kehuListKeys: number;
  kehuSearchKeys: number;
  kehuAdvSearchKeys: number;
  latency: string;
  uptimeInSeconds: string;
  uptimeInDays: string;
  memoryFragmentationRatio: string;
  expiredKeysCount: string;
  evictedKeysCount: string;
  keyspaceHits: string;
  keyspaceMisses: string;
  rejectedConnections: string;
}

export interface RedisClearResult {
  count: number;
  message: string;
}

export interface RedisPerformanceMetrics {
  isEnabled: boolean;
  message: string;
  benchmarkResults: {[key: string]: string};
  memoryStats: {[key: string]: string};
  commandStats: {[key: string]: number};
  setOperationsPerSecond: number;
  getOperationsPerSecond: number;
}

@Injectable({
  providedIn: 'root'
})
export class RedisCacheService {
  apiName = 'Default';

  constructor(private restService: RestService) {}

  /**
   * 获取Redis状态信息
   */
  getStatus(): Observable<RedisStatusDto> {
    return this.restService.request<any, RedisStatusDto>({
      method: 'GET',
      url: '/api/redis/status'
    }).pipe(
      catchError(error => {
        console.error('获取Redis状态失败', error);
        throw error;
      })
    );
  }

  /**
   * 清除指定模式的缓存
   * @param pattern 缓存键模式
   */
  clearCache(pattern: string): Observable<RedisClearResult> {
    return this.restService.request<any, RedisClearResult>({
      method: 'DELETE',
      url: '/api/redis/clear',
      params: { pattern }
    }).pipe(
      catchError(error => {
        console.error('清除Redis缓存失败', error);
        throw error;
      })
    );
  }

  /**
   * 清除所有客户相关缓存
   */
  clearKehuCache(): Observable<RedisClearResult> {
    return this.restService.request<any, RedisClearResult>({
      method: 'DELETE',
      url: '/api/redis/clear-kehu-cache'
    }).pipe(
      catchError(error => {
        console.error('清除客户缓存失败', error);
        throw error;
      })
    );
  }

  /**
   * 获取Redis性能指标
   */
  getPerformanceMetrics(): Observable<RedisPerformanceMetrics> {
    return this.restService.request<any, RedisPerformanceMetrics>({
      method: 'GET',
      url: '/api/redis/performance'
    }).pipe(
      catchError(error => {
        console.error('获取Redis性能指标失败', error);
        throw error;
      })
    );
  }

  /**
   * 生成测试数据（仅开发环境使用）
   * @param count 生成数量，默认1000
   */
  generateTestData(count: number = 1000): Observable<any> {
    return this.restService.request<any, any>({
      method: 'POST',
      url: '/api/redis/generate-test-data',
      params: { count }
    }).pipe(
      catchError(error => {
        console.error('生成测试数据失败', error);
        throw error;
      })
    );
  }

  /**
   * 计算缓存命中率百分比
   */
  calculateHitRatePercentage(status: RedisStatusDto): number {
    if (!status.keyspaceHits || !status.keyspaceMisses) {
      return 0;
    }
    
    const hits = parseInt(status.keyspaceHits, 10);
    const misses = parseInt(status.keyspaceMisses, 10);
    
    if (hits === 0 && misses === 0) {
      return 0;
    }
    
    return Math.round((hits / (hits + misses)) * 100);
  }

  /**
   * 计算内存使用率百分比
   */
  calculateMemoryUsagePercentage(status: RedisStatusDto): number {
    if (!status.usedMemory || !status.maxMemory) {
      return 0;
    }
    
    // 尝试从格式化字符串中提取数值部分
    const usedMatch = status.usedMemory.match(/(\d+(\.\d+)?)/);
    const maxMatch = status.maxMemory.match(/(\d+(\.\d+)?)/);
    
    if (!usedMatch || !maxMatch) {
      return 0;
    }
    
    const used = parseFloat(usedMatch[0]);
    const max = parseFloat(maxMatch[0]);
    
    if (max === 0) {
      return 0;
    }
    
    return Math.round((used / max) * 100);
  }
} 